package com.mxpio.erp.plm.controller;

import com.mxpio.erp.common.enums.PlmEnums;
import com.mxpio.erp.common.enums.PlmEnums;
import com.mxpio.erp.common.plm.bo.ProjectTaskBO;
import com.mxpio.erp.common.plm.entity.ProjectInfo;
import com.mxpio.erp.common.plm.entity.ProjectInfoChange;
import com.mxpio.erp.common.plm.entity.ProjectTask;
import com.mxpio.erp.common.plm.entity.ProjectTaskComplete;
import com.mxpio.erp.common.plm.service.ProjectInfoService;
import com.mxpio.erp.common.plm.service.ProjectTaskService;
import com.mxpio.erp.common.plm.vo.ProjectTaskVO;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import javax.management.MBeanException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Tag(name = "ProjectTaskController", description = "项目任务计划")
@RestController
@RequestMapping("/erp/plm/pro/task/")
public class ProjectTaskController {

    @Autowired
    private ProjectTaskService projectTaskService;

    @Autowired
    private ProjectInfoService projectInfoService;

    @GetMapping("tree/{proCode}")
    @Operation(summary = "获取任务树", description = "获取任务树", method = "GET")
    public Result<List<ProjectTask>> listTree(@PathVariable(name = "proCode", required = true) String proCode,@Parameter(description="查询参数") Criteria criteria) throws UnsupportedEncodingException {
        criteria = criteria.addCriterion("proCode", Operator.EQ, proCode);
        List<ProjectTask> projectTask = projectTaskService.tree(ProjectTask.class, criteria);
        return Result.OK(projectTask);
    }

    @GetMapping("list")
    @Operation(summary = "项目任务列表", description = "项目任务列表（无分页）", method = "GET")
    public Result<List<ProjectTask>> list(@Parameter(description="查询参数") Criteria criteria) throws UnsupportedEncodingException {
        List<ProjectTask> list = projectTaskService.list(ProjectTask.class, criteria);
        return Result.OK(list);
    }

    @GetMapping("page")
    @Operation(summary = "项目任务列表", description = "项目任务列表（分页）", method = "GET")
    public Result<Page<ProjectTask>> page(@Parameter(description="查询参数") Criteria criteria, @Parameter(description="每页条数")Integer pageSize, @Parameter(description="页号")Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        Page<ProjectTask> pageResult = projectTaskService.listPage(ProjectTask.class, page, criteria);
        return Result.OK(pageResult);
    }

    @GetMapping("list/{proCode}")
    @Operation(summary = "根据项目编码获取任务列表", description = "根据项目编码获取任务列表", method = "GET")
    public Result<List<ProjectTask>> getByProId(@PathVariable(name = "proCode", required = true) String proCode) {
        Criteria criteria = Criteria.create();
        Criteria criteria1 = criteria.addCriterion("proCode", Operator.EQ, proCode);
        List<ProjectTask> tasks = projectTaskService.list(ProjectTask.class, criteria1);
        return Result.OK(tasks);
    }

    @GetMapping("list/task/{taskCode}")
    @Operation(summary = "根据任务编码获取任务列表", description = "根据任务编码获取任务列表", method = "GET")
    public Result<ProjectTask> getByTaskId(@PathVariable(name = "taskCode", required = true) String taskCode) {
        ProjectTask tasks = projectTaskService.getById(ProjectTask.class, taskCode);
        return Result.OK(tasks);
    }

    @GetMapping("page/my")
    @Operation(summary = "我参与的项目任务列表", description = "我参与的项目任务列表（分页）", method = "GET")
    public Result<Page<ProjectTask>> myTask(@Parameter(description="查询参数") Criteria criteria, @Parameter(description="每页条数")Integer pageSize, @Parameter(description="页号")Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        criteria = criteria.addCriterion("taskMembers", Operator.LIKE, "%,"+ SecurityUtils.getLoginUsername() +",%");
        Page<ProjectTask> pageResult = projectTaskService.listPage(ProjectTask.class, page, criteria);
        return Result.OK(pageResult);
    }
    @GetMapping("page/head")
    @Operation(summary = "我负责的项目任务列表", description = "我负责的项目任务列表（分页）", method = "GET")
    public Result<Page<ProjectTask>> pageHead(@Parameter(description="查询参数") Criteria criteria, @Parameter(description="每页条数")Integer pageSize, @Parameter(description="页号")Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        criteria = criteria.addCriterion("head", Operator.LIKE, "%,"+ SecurityUtils.getLoginUsername() +",%");
        Page<ProjectTask> pageResult =projectTaskService.headAll(page, criteria);
//        List<ProjectTask> tree = projectTaskService.tree(ProjectTask.class, criteria);
//        for (ProjectTask projectTask : tree){
//            ProjectTask byId = projectTaskService.getById(ProjectTask.class, projectTask.getTaskCode());
//            byId.setHavaChildren("false");
//            projectTaskService.update(byId);
//            if (projectTask.getChildren().size()>0 && projectTask.getChildren() !=null ){
//                byId.setHavaChildren("true");
//                projectTaskService.update(byId);
//            }
//        }
////        PageImpl<ProjectTask> projectTasks = new PageImpl<>(tree, page, tree.size());
//
//        Page<ProjectTask> pageResult = projectTaskService.listPage(ProjectTask.class, page, criteria);
        return Result.OK(pageResult);
    }

    @GetMapping("page/approval")
    @Operation(summary = "项目任务列表", description = "项目任务列表（分页）", method = "GET")
    public Result<Page<ProjectTaskVO>> pageApproval(@Parameter(description="查询参数") Criteria criteria, @Parameter(description="每页条数")Integer pageSize, @Parameter(description="页号")Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        criteria = criteria.addCriterion("head", Operator.LIKE, "%,"+ SecurityUtils.getLoginUsername() +",%");
        Page<ProjectTaskVO> pageResult = projectTaskService.pageApproval(page, criteria);
        return Result.OK(pageResult);
    }

    @GetMapping("check-circular/{taskCode}/{beforeTaskCode}")
    @Operation(summary = "检查任务循环依赖", description = "检查给定任务是否存在循环依赖")
    public Result<?> checkCircularDependency(@PathVariable String taskCode, @PathVariable String beforeTaskCode) {
        ProjectTask projectTask = projectTaskService.getById(ProjectTask.class, taskCode);
        boolean hasCycle = projectTaskService.checkForCircularDependency(projectTask, beforeTaskCode);
        if (hasCycle) {
            return Result.error("存在循环依赖！");
        }
        return Result.OK("没有循环依赖");
    }


    @RequestMapping("add")
    @Operation(summary = "保存项目任务信息", description = "保存项目任务信息")
    public Result<?> add(@RequestBody ProjectTask projectTask) {
        try {
           return projectTaskService.saveTask(projectTask);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }
//        return Result.OK(projectTask);
    }

    @PutMapping("edit")
    @Operation(summary = "编辑项目任务信息", description = "编辑项目任务信息", method = "PUT")
    public Result<?> edit(@RequestBody ProjectTask projectTask) {
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTask.getTaskCode());
//        if(task ==  null || !PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode().equals(task.getExecutionStatus())){
//            return Result.error("当前任务状态不允许编辑！");
//        }

        if(projectTask.getTaskCode().equals(projectTask.getParentTaskCode())){
            return Result.error("自己不能为自己的父任务");
        }

        if(projectTask.getTaskCode().equals(projectTask.getBeforeTask())){
            return Result.error("前置任务不能与本任务一致");
        }
        return projectTaskService.editTask(projectTask);
//        return Result.OK(projectTask);
    }

    @DeleteMapping(value = "/delete/{taskCode}")
    @Operation(summary = "删除项目任务信息",description = "删除项目任务信息", method = "DELETE")
    public Result<?> delete(@PathVariable(name = "taskCode") String taskCode) {
        ProjectTask task = projectTaskService.getById(ProjectTask.class, taskCode);
        if(task ==  null || StringUtils.isNotEmpty(task.getAfterTask())){
            return Result.error("存在后置任务不允许删除！");
        }

        if(!PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode().equals(task.getExecutionStatus())){
            return Result.error("当前任务状态不允许删除！");
        }
        projectTaskService.deleteTask(taskCode);
        return Result.OK("删除成功");
    }

    @PutMapping("upgrade/{taskCode}")
    @Operation(summary = "升级任务", description = "根据任务编码升级任务", method = "PUT")
    public Result<?> upgrade(@PathVariable(name = "taskCode", required = true) String taskCode) {
        try {
            projectTaskService.upgradeTask(taskCode);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }
        return Result.OK("任务升级成功");
    }

    @PutMapping("downgrade/{taskCode}")
    @Operation(summary = "降级任务", description = "根据任务编码降级任务", method = "PUT")
    public Result<?> downgrade(@PathVariable(name = "taskCode", required = true) String taskCode) {
        try {
            projectTaskService.downgradeTask(taskCode);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }
        return Result.OK("任务降级成功");
    }

    @PutMapping("moveUp/{taskCode}")
    @Operation(summary = "上移项目任务", description = "根据任务编码上移项目任务", method = "PUT")
    public Result<?> moveTaskUp(@PathVariable(name = "taskCode", required = true) String taskCode) {
        projectTaskService.moveTaskUp(taskCode);
        return Result.OK("任务上移成功");
    }

    @PutMapping("moveDown/{taskCode}")
    @Operation(summary = "下移项目任务", description = "根据任务编码下移项目任务", method = "PUT")
    public Result<?> moveTaskDown(@PathVariable(name = "taskCode", required = true) String taskCode) {
        projectTaskService.moveTaskDown(taskCode);
        return Result.OK("任务下移成功");
    }

    @PutMapping("start/{taskCode}")
    @Operation(summary = "启动任务", description = "根据任务编码启动任务", method = "PUT")
    public Result<?> start(@PathVariable(name = "taskCode", required = true) String taskCode) {
        //判断任务状态
        ProjectTask task = projectTaskService.getById(ProjectTask.class, taskCode);
        if(task == null || !PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode().equals(task.getExecutionStatus())){
            return Result.error("任务不存在或任务状态错误！");
        }
        //判断项目状态
        ProjectInfo project = projectInfoService.getById(ProjectInfo.class, task.getProCode());
        if(!PlmEnums.ProStatus.EXECUT.getCode().equals(project.getProStatus())){
            return Result.error("当前项目状态不允许启动操作！");
        }

        try {
            projectTaskService.start(task);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }
        return Result.OK("任务启动成功");
    }

    @PutMapping("execute")
    @Operation(summary = "执行任务-执行日志填报", description = "根据任务编码执行任务-执行日志填报", method = "PUT")
    public Result<?> executeTask(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        // 判断任务状态是否允许执行
        if(!PlmEnums.ExecutionStatus.EXECUTING.getCode().equals(task.getExecutionStatus())) {
            return Result.error("任务状态不允许执行！");
        }

        // 判断项目状态是否允许执行任务
        ProjectInfo project = projectInfoService.getById(ProjectInfo.class, task.getProCode());
        if(!PlmEnums.ProStatus.EXECUT.getCode().equals(project.getProStatus())) {
            return Result.error("当前项目状态不允许执行任务！");
        }

        // 检查进度值是否有效
        if (projectTaskBO.getProgress().compareTo(task.getProgress()) < 0
                || projectTaskBO.getProgress().compareTo(BigDecimal.valueOf(100)) > 0) {
            return Result.error("进度更新无效：不可低于当前进度且不可超过100%");
        }

        try {
            projectTaskService.executeTask(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务执行成功");
    }

    @PutMapping("finish")
    @Operation(summary = "任务完工申请", description = "任务完工申请", method = "PUT")
    public Result<?> finishTask(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        // 判断任务状态是否允许执行
        if(!PlmEnums.ExecutionStatus.EXECUTING.getCode().equals(task.getExecutionStatus())) {
            return Result.error("任务状态不允许执行完工申请！");
        }


        // 检查进度值是否有效
        if (projectTaskBO.getProgress().compareTo(task.getProgress()) < 0
                || projectTaskBO.getProgress().compareTo(BigDecimal.valueOf(100)) > 0) {
            return Result.error("进度更新无效：不可低于当前进度且不可超过100%");
        }

        try {
            projectTaskService.finishTask(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务执行成功");
    }
    @PutMapping("finishAudit")
    @Operation(summary = "任务完工审核", description = "任务完工审核", method = "PUT")
    public Result<?> finishAudit(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        try {
            projectTaskService.finishAudit(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务完工审核成功");
    }

    /**
     * 工作流审核-任务完工
     * @param
     * @return
     */
    @PutMapping("finishAudit/workflows")
    @Operation(summary = "任务完工审核-工作流模式", description = "任务完工审核-工作流模式", method = "PUT")
    public Result<?> finishAuditWorkflows(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }
        return projectTaskService.finishAuditWorkflows(projectTaskBO);
    }

    /**
     * 任务完工-工作流-发起申请
     * @param key
     * @param businessKey
     * @param properties
     * @return
     */
    @RequestMapping("finishAuditWork/{key}")
    @Operation(summary = "任务完工申请-工作流",description = "任务完工申请-工作流")
    public Result<?> finishAuditWork(@PathVariable(name = "key") String key,
                            @RequestParam(value="businessKey", required = false) String businessKey,
                            @RequestBody Map<String, Object> properties) {
        return projectTaskService.finishAuditWork(key, SecurityUtils.getLoginUsername(), businessKey, properties);
    }

    /**
     * 任务完工-工作流-审核
     * @param projectTaskBO
     * @return
     */
    @RequestMapping("finishAudit/workOK")
    @Operation(summary = "任务完工审核-工作流",description = "任务完工审核-工作流")
    public Result<?> finishAuditOk(@RequestBody ProjectTaskBO projectTaskBO) {
        return projectTaskService.finishAuditWorkOK(projectTaskBO);
    }

    @PutMapping("change")
    @Operation(summary = "任务变更申请", description = "任务变更申请", method = "PUT")
    public Result<?> changeTask(@RequestBody ProjectTask projectTask) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTask.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        // 判断任务状态是否允许变更申请
        if(!PlmEnums.ExecutionStatus.EXECUTING.getCode().equals(task.getExecutionStatus())) {
            return Result.error("任务状态不允许执行变更申请！");
        }

        if(projectTask.getTaskCode().equals(projectTask.getParentTaskCode())){
            return Result.error("父任务不能修改为子任务");
        }

        if(projectTask.getTaskCode().equals(projectTask.getBeforeTask())){
            return Result.error("前置任务不能与本任务一致");
        }

        try {
            // 记录任务变更申请日志
            projectTaskService.changeTask(projectTask);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务变更申请成功");
    }

    @PutMapping("changeAudit")
    @Operation(summary = "任务变更审核", description = "任务变更审核", method = "PUT")
    public Result<?> changeAudit(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }
        try {
            projectTaskService.changeAudit(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务变更审核成功");
    }

    @PutMapping("close")
    @Operation(summary = "任务关闭申请", description = "任务关闭申请", method = "PUT")
    public Result<?> closeTask(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        try {
            projectTaskService.closeTask(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务关闭申请成功");
    }

    @PutMapping("closeAudit")
    @Operation(summary = "任务关闭审核", description = "任务关闭审核", method = "PUT")
    public Result<?> closeAudit(@RequestBody ProjectTaskBO projectTaskBO) {
        // 获取任务信息
        ProjectTask task = projectTaskService.getById(ProjectTask.class, projectTaskBO.getTaskCode());
        if(task == null) {
            return Result.error("任务不存在！");
        }

        try {
            projectTaskService.closeTaskAudit(task, projectTaskBO);
        }catch (MBootException e){
            return Result.error(e.getMessage());
        }

        return Result.OK("任务关闭审核成功");
    }

    @GetMapping("get/child/de/{taskCode}")
    @Operation(summary = "根据任务编码查询当前任务下包括后代的交付物-分页", description = "根据任务编码查询当前任务下包括后代的交付物-分页", method = "GET")
    public Result<?> getChildDeliverable(@PathVariable(name = "taskCode", required = true) String taskCode,
                                        @Parameter(description="每页条数")Integer pageSize,
                                         @Parameter(description="页号")Integer pageNo,
                                         @Parameter(description="查询参数") Criteria criteria) {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        return projectTaskService.getChildDeliverable(taskCode,page,criteria);
    }


}
